import createVanilla from 'zustand/vanilla'
import { subscribeWithSelector } from 'zustand/middleware'
import create from 'zustand'
import { getBitrate, SelectedMt, SelectedMtModel, SelectMtEntity } from '../../translator'
import { CONSTANT } from '../../utils/utils'
import { store as addMtStore } from '../../store'

type SelectedOption = {
	selectedList: SelectedMtModel[]
	_prevClickSelectItem: { start: string; prevChosen: string[] } | null
}
type IStore = SelectedOption & {
	update: (d: Partial<SelectedOption>) => void
	reset: () => void
	initSelectedList: (selectedEntityMts: SelectMtEntity[]) => void
	changeProtocol: (item: SelectedMt, protocol: 0 | 1 | 2 | 255) => void
	changeRateBySelect: (item: SelectedMt, selectVal: number) => void
	changeRateByInput: (item: SelectedMt, inputVal: string) => void
	changeCallType: (item: SelectedMt, val: string) => void
	clickSelectItem: (data: SelectedMtModel, { ctrlKey, shiftKey }: { ctrlKey: boolean; shiftKey: boolean }) => void
	checkSelectItem: (data: SelectedMtModel) => void
	changeItemType: (data: SelectedMtModel) => void
	toggleMoreOpt: (data: SelectedMtModel) => void
	addItem: (data: SelectedMtModel) => void
	addList: (dataList: SelectedMtModel[]) => void
	removeItem: (data: SelectedMtModel) => void
	removeSelected: () => void
	removeAllSelected: () => void
	delAllSelectedRooms: () => void
	delSelectedRooms: (rooms: SelectMtEntity[]) => void
}
const initialState: SelectedOption = {
	selectedList: [],
	_prevClickSelectItem: null,
}

export const store = createVanilla<IStore>()(
	subscribeWithSelector((set, get) => ({
		...initialState,
		update: (d) => set({ ...d }),
		reset: () => set(initialState),
		initSelectedList: (selectedEntityMts) => {
			let list = selectedEntityMts.map((x) => new SelectedMtModel(x))
			set({ selectedList: list })
		},
		changeProtocol: (item, protocol) => {
			let list = get().selectedList
			item.protocol = protocol
			set({ selectedList: [...list] })
		},
		changeRateBySelect: (item, selectVal) => {
			let list = get().selectedList
			let maxRate = addMtStore.getState().maxRate
			if (selectVal !== 0) {
				item.bitrate = getBitrate(selectVal)
				item.bitrateType = selectVal
			} else {
				//自定义
				item.bitrateType = 0
				item.bitrate = maxRate
			}
			set({ selectedList: [...list] })
		},
		changeRateByInput: (item, inputVal) => {
			let list = get().selectedList
			let maxRate = addMtStore.getState().maxRate
			let bitrate = parseInt(inputVal.trim())
			if (bitrate < 64) {
				bitrate = 64
			} else if (bitrate < maxRate) {
				if (bitrate % 64 !== 0) {
					//取整
					bitrate = bitrate + 64 - (bitrate % 64)
				}
			} else {
				bitrate = maxRate
			}
			item.bitrate = bitrate
			set({ selectedList: [...list] })
		},
		changeCallType: (item, val) => {
			let list = get().selectedList
			let maxRate = addMtStore.getState().maxRate
			if (val === 'audio') {
				//音频呼叫
				item.bitrateType = 0
				item.bitrate = 64
			} else {
				//如果之前是64的语音呼叫 切换为视频/手机呼叫时变成会议最大码率
				if (item.bitrate === 64) {
					item.bitrateType = 0
					item.bitrate = maxRate
				}
			}
			//视频终端 电话终端 相互切换
			if (
				item.accountType === CONSTANT.accountType.phone ||
				item.accountType === CONSTANT.accountType.softTerminal
			) {
				if (val === 'video') {
					item.account = item.moid
					item.accountType = CONSTANT.accountType.softTerminal
				} else if (val === 'phone') {
					item.account = item.mobilePhone || item.workPhone
					item.accountType = CONSTANT.accountType.phone
				}
			}
			set({ selectedList: [...list] })
		},
		clickSelectItem: (data, { ctrlKey, shiftKey }) => {
			let list = get().selectedList
			let prevClickSelectItem = get()._prevClickSelectItem
			if (shiftKey) {
				if (prevClickSelectItem) {
					const { start, prevChosen } = prevClickSelectItem
					if (prevChosen.length > 0) {
						//说明已经有过一次shift操作，需要把这次操作结果复原
						for (let i = 0; i < list.length; i++) {
							const item = list[i]
							if (prevChosen.includes(item.id)) {
								item.status.isSelected = false
								item.status.isOpenMoreOpt = false
							}
						}
					}
					const startItem = list.find((x) => x.id === start)
					let newChosen = []
					if (!startItem || startItem.id === data.id) {
						//初始值没了，那就重新记录;或者初始值和当前值一样
						data.status.isSelected = true
						prevClickSelectItem.start = data.id
					} else {
						let _flag = false,
							_time = 0
						for (let i = 0; i < list.length; i++) {
							const item = list[i]
							if (item.id === data.id || item.id === start) {
								item.status.isSelected = true
								newChosen.push(item.id)
								_flag = ++_time === 1
							}
							if (_flag) {
								item.status.isSelected = true
								newChosen.push(item.id)
							}
						}
					}
					prevClickSelectItem.prevChosen = newChosen
				} else {
					data.status.isSelected = true
					prevClickSelectItem = { start: data.id, prevChosen: [] }
				}
			} else {
				if (ctrlKey) {
					data.status.isSelected = !data.status.isSelected
					data.status.isOpenMoreOpt = false
				} else {
					for (let i = 0; i < list.length; i++) {
						const item = list[i]
						item.status.isSelected = false
						item.status.isOpenMoreOpt = false
					}
					data.status.isSelected = true
				}
				prevClickSelectItem = { start: data.id, prevChosen: [] }
			}
			set({ selectedList: [...list], _prevClickSelectItem: prevClickSelectItem })
		},
		checkSelectItem: (data) => {
			let clickSelectItem = get().clickSelectItem
			clickSelectItem(data, { ctrlKey: true, shiftKey: false })
		},
		changeItemType: (data) => {
			let list = get().selectedList
			let isSuperMeeting = addMtStore.getState().isSuperMeeting
			if (isSuperMeeting) {
				data.attr.isInteractiveMt = !data.attr.isInteractiveMt
			} else {
				data.attr.isOftenMt = !data.attr.isOftenMt
			}
			set({ selectedList: [...list] })
		},
		toggleMoreOpt: (data) => {
			let list = get().selectedList
			data.status.isOpenMoreOpt = !data.status.isOpenMoreOpt
			data.status.isSelected = true
			set({ selectedList: [...list] })
		},
		addItem: (data) => {
			let list = get().selectedList
			let mccCurrentMts = addMtStore.getState().mccCurrentMts
			//去重
			let _list = [...list.map((x) => x.item), ...mccCurrentMts]
			for (let i = 0; i < _list.length; i++) {
				const item = _list[i]
				if (data.item.moid && item.moid === data.item.moid) {
					return
				}
				if (item.account === data.item.account && item.accountType === data.item.accountType) {
					return
				}
			}
			//排序 把人放到模板前面，模板往后排
			const firstTemplateIndex = list.findIndex((x) => x.attr.isMeeting)
			if (firstTemplateIndex !== -1) {
				if (data.attr.isMeeting) {
					set({ selectedList: [...list, data] })
				} else {
					set({
						selectedList: [...list.slice(0, firstTemplateIndex), data, ...list.slice(firstTemplateIndex)],
					})
				}
			} else {
				set({ selectedList: [...list, data] })
			}
		},
		addList: (dataList) => {
			let list = get().selectedList
			let mccCurrentMts = addMtStore.getState().mccCurrentMts
			let uniqDataList: SelectedMtModel[] = []
			//去重
			let _list = [...list.map((x) => x.item), ...mccCurrentMts]
			for (let i = 0; i < dataList.length; i++) {
				const data = dataList[i]
				let flag = true
				for (let i = 0; i < _list.length; i++) {
					const item = _list[i]
					if (data.item.moid && item.moid === data.item.moid) {
						flag = false
						break
					}
					if (item.account === data.item.account && item.accountType === data.item.accountType) {
						flag = false
						break
					}
				}
				if (flag) uniqDataList.push(data)
			}
			//排序 把人放到模板前面，模板往后排
			const firstTemplateIndex = list.findIndex((x) => x.attr.isMeeting)
			if (firstTemplateIndex !== -1) {
				const firstIndex = uniqDataList.findIndex((x) => x.attr.isMeeting)
				set({
					selectedList: [
						...list.slice(0, firstTemplateIndex),
						...uniqDataList.slice(0, firstIndex),
						...list.slice(firstTemplateIndex),
						...uniqDataList.slice(firstIndex),
					],
				})
			} else {
				set({ selectedList: [...list, ...uniqDataList] })
			}
		},
		removeItem: (data) => {
			let list = get().selectedList
			if (data.item.accountType === CONSTANT.accountType.meetingRoom) {
				addMtStore.getState().onRemoveRoom()
			} else {
				let r = list.filter(
					(x) => !(x.item.account === data.item.account && x.item.accountType === data.item.accountType)
				)
				set({ selectedList: [...r] })
			}
		},
		removeSelected: () => {
			let list = get().selectedList
			let r = list.filter((x) => !x.status.isSelected || x.item.accountType === CONSTANT.accountType.meetingRoom)
			set({ selectedList: [...r] })
			let room = list.find((x) => x.status.isSelected && x.item.accountType === CONSTANT.accountType.meetingRoom)
			if (room) {
				addMtStore.getState().onRemoveRoom()
			}
		},
		removeAllSelected: () => {
			let list = get().selectedList
			let roomList = list.filter((x) => x.item.accountType === CONSTANT.accountType.meetingRoom)
			set({ selectedList: [...roomList] })
			if (roomList.length > 0) {
				addMtStore.getState().onRemoveRoom()
			}
		},
		delAllSelectedRooms: () => {
			let list = get().selectedList
			let r = list.filter((x) => x.item.accountType !== CONSTANT.accountType.meetingRoom)
			set({ selectedList: [...r] })
		},
		delSelectedRooms: (rooms) => {
			let addList = get().addList
			addList(rooms.map((x) => new SelectedMtModel(x)))
		},
	}))
)
/**
 * 替代了useEffect的监听，把 store 相关的一些都集成到store里
 * 仅是尝试如此使用，react的状态管理基本都没有直接好用的类似于 vue watch 的方法，全是subscribe的监听
 *
 * subscribe：store初始值 依赖函数不会执行，只有值改变才会执行依赖函数
 * 和 useEffect 还是有区别的，useEffect 即使是初始值，函数也会执行
 * 所以需要保证 store 内的初始值都是正确的，尤其是通过 subscribe 相互监听调用更新的 store 值
 */
addMtStore.subscribe(
	(state) => state.mccCurrentMts,
	(mccCurrentMts) => {
		let list = store.getState().selectedList
		let uniqDataList: SelectedMtModel[] = []
		//去重
		for (let i = 0; i < list.length; i++) {
			const data = list[i]
			let flag = true
			for (let i = 0; i < mccCurrentMts.length; i++) {
				const item = mccCurrentMts[i]
				if (data.item.moid && item.moid === data.item.moid) {
					flag = false
					break
				}
				if (item.account === data.item.account && item.accountType === data.item.accountType) {
					flag = false
					break
				}
			}
			if (flag) uniqDataList.push(data)
		}
		store.setState({ selectedList: uniqDataList })
	}
)
export const useSelectedStore = create(store)
